/*************************************************************/
/*                           MS3D.H                          */
/*                                                           */
/* Purpose: Class and data structures to load, render and    */
/*          animate Milkshape 3D MS3D files                  */
/*                                                           */
/*************************************************************/

#ifndef __MODELEDITOR_MS3D_H
#define __MODELEDITOR_MS3D_H

#include "../ModelEditorConfig.h"
#include "Model.h"

#pragma pack(push, packing)
#pragma pack(1)

//- SMs3dVertex		- A single vertex data structure
struct SMs3dVertex
{
	unsigned char m_ucFlags;			//Editor flags, unused for the loader
	float m_vVert[3];					//X,Y,Z coordinates
	char m_cBone;						//Bone ID (-1 = no bone)
	unsigned char m_ucUnused;
};

//-------------------------------------------------------------
//- SMs3dTriangle	- Triangle data structure
struct SMs3dTriangle
{
	unsigned short m_usFlags;			//Editor flags (unused for loader)
	unsigned short m_usVertIndices[3];	//Vertex indices
	float m_vNormals[3][3];				//Vertex normals;
	float m_fTexCoords[2][3];			//Texture coordinates
	unsigned char m_ucSmoothing;		//Smoothing group
	unsigned char m_ucGroup;			//Group index
};

//-------------------------------------------------------------
//- SMs3dMesh		- Group of triangles in the ms3d file
struct SMs3dMesh
{
	unsigned char m_ucFlags;			//Editor flags again
	char m_cName[32];					//Name of the mesh
	unsigned short m_usNumTris;			//Number of triangles in the group
	unsigned short *m_uspIndices;		//Triangle indices
	char m_cMaterial;					//Material index, -1 = no material

	//Let itclean up after itself like usual
	SMs3dMesh()
	{
		m_uspIndices = NULL;
	}
	~SMs3dMesh()
	{
		if(m_uspIndices)
		{
			delete [] m_uspIndices;
			m_uspIndices = NULL;
		}
	}
};

//-------------------------------------------------------------
//- SMs3dMaterial	- Material information for the mesh
struct SMs3dMaterial
{
	char m_cName[32];					//Material name
	float m_fAmbient[4];				//Ambient values
	float m_fDiffuse[4];				//Diffuse values
	float m_fSpecular[4];				//Specular values
	float m_fEmissive[4];				//Emissive values
	float m_fShininess;					//0 - 128
	float m_fTransparency;				//0 - 1
	char m_cMode;						//unused
	char m_cTexture[128];				//Texture map file
	char m_cAlpha[128];					//Alpha map file

};


//-------------------------------------------------------------
//- SMs3dKeyFrame	- Rotation/Translation information for joints
struct SMs3dKeyFrame
{
	float m_fTime;						//Time at which keyframe is started
	float m_fParam[3];					//Translation or Rotation values
};

//-------------------------------------------------------------
//- SMs3dJoint		- Bone Joints for animation
struct SMs3dJoint
{
	//Data from file
	unsigned char m_ucpFlags;			//Editor flags
	char m_cName[32];					//Bone name
    char m_cParent[32];					//Parent name
    float m_fStartRotation[3];			//Starting rotation
    float m_fStartPosition[3];			//Starting position
	unsigned short m_usNumRotFrames;	//Number of rotation frames
    unsigned short m_usNumTransFrames;	//Number of translation frames

    SMs3dKeyFrame *m_RotKeyFrames;		//Rotation keyframes
    SMs3dKeyFrame *m_TransKeyFrames;	//Translation keyframes

	//Data not loaded from file
	short m_sParent;					//Parent joint index
	
	OyMatrix m_matLocal;       
	OyMatrix m_matAbs;
	OyMatrix m_matFinal;

	//unsigned short m_usCurRotFrame;
	//unsigned short m_usCurTransFrame;

	 //Clean up after itself like usual
	SMs3dJoint()
	{
		m_RotKeyFrames = NULL;
		m_TransKeyFrames = NULL;
		//m_usCurRotFrame = 0;
		//m_usCurTransFrame = 0;
	}
	~SMs3dJoint()
	{
		if(m_RotKeyFrames)
		{
			delete [] m_RotKeyFrames;
			m_RotKeyFrames = NULL;
		}
		if(m_TransKeyFrames)
		{
			delete [] m_TransKeyFrames;
			m_TransKeyFrames = NULL;
		}
	}
};

#pragma pack(pop, packing)


//-------------------------------------------------------------
class CMs3d : public CModel
{
public:
	//Load the MS3D file
	virtual bool Load(const char *szFilename);
	// Sets the scaling of the model. 0.0f for no scaling.
	virtual void SetScaling( float fScale = 0.0f );
	// Get the number of Animnation from file
	virtual UINT GetAnimationListNum() { return 0; }
	virtual const char* GetAnimationName(UINT AnimID) { return NULL; }

	// Create MS3D Static Mesh at the initial position
	virtual void CreateStaticMesh(UINT DefaultSkinID);
	virtual void Render(float ElapsedSeconds);

	// Model Type
	virtual EModelType GetModelType() { return EModel_MS3D; }

	// Get the time of Anim named "szAnimName"
	void GetAnimTime(const char *szAnimName, float &AnimTimeStart, float &AnimTimeEnd);

	// Bind correct texture files to according material skin in the ms3d files itself
	void BindTexture();
/*
	//Turn the drawing of bones on and off
	void SwapBoneDraw();
	//Turn the drawing of the mesh on and off
	void SwapMeshDraw();
	//Check if displays of bones and meshes are on or off
	bool AreBonesEnabled();
	bool AreMeshesEnabled();
*/

	//Constructors
	CMs3d();
	CMs3d(const char *szFilename);
	//Destructor
	~CMs3d();

private:

	// Animate the model from based on time (seconds)
	void RenderAnimate(UINT DefaultSkinID, float ElapsedSeconds, float fSpeed, float fStartTime, float fEndTime, bool bLoop);
	// Texture file name in struct SMs3dMaterial usually has error file's extension,
	// this function find correct file's extension in local path
	bool BindCorrectTextureName(TCHAR (&TexName) [128]);


	//Setup joints
	void Setup();

	//Render the transformed vertices
	void RenderTransVert(UINT DefaultSkinID);

	//Total time for model animation
	float m_fTotalTime;

	//Data
	unsigned short m_usNumVerts;
	unsigned short m_usNumTriangles;
	unsigned short m_usNumMeshes;
	unsigned short m_usNumMaterials;
	unsigned short m_usNumJoints;

	SMs3dVertex *m_pVertices;
	SMs3dTriangle *m_pTriangles;
	SMs3dMesh *m_pMeshes;
	SMs3dMaterial *m_pMaterials;
	SMs3dJoint *m_pJoints;

	TCHAR m_CurrentPath[128];					// current file path
	TCHAR m_CurrentTexName[128];				// current Texture name
	OY_UNORMALCOLORTEX_VERTEX_TYPE **m_ppSMVB;	// Vertex for rendering for each Mesh 
	UINT *m_pSMSkinID;							// SkinID for each Mesh
};

#endif